package com.yfp.operation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.util.StringUtil;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.yfp.common.core.domain.LogisticsInfoVO;
import com.yfp.common.core.domain.R;
import com.yfp.common.core.domain.Response;
import com.yfp.common.core.domain.ResponseEnum;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.minapp.auth.api.RemoteClientService;
import com.yfp.operation.domain.MallOrder;
import com.yfp.operation.domain.dto.EnteringLogisticsSnDTO;
import com.yfp.operation.domain.dto.LogisticsInfoDTO;
import com.yfp.operation.domain.dto.MallOrderListDTO;
import com.yfp.operation.domain.vo.MallOrderListVO;
import com.yfp.operation.enums.MallOrderStatusEnum;
import com.yfp.operation.mapper.MallOrderDetailsMapper;
import com.yfp.operation.service.MallOrderService;
import com.yfp.operation.mapper.MallOrderMapper;
import com.yfp.operation.utils.DateUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.yfp.common.core.constant.CacheConstants.MINAPP_ORDER_LOGISTICS_INFO_KEY;

/**
* @author admin
* @description 针对表【mall_order(商城订单)】的数据库操作Service实现
* @createDate 2025-03-05 11:03:51
*/
@Service
@Slf4j
public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder> implements MallOrderService{

    @Resource
    private MallOrderMapper mallOrderMapper;
    @Resource
    private MallOrderDetailsMapper mallOrderDetailsMapper;
    @Resource
    private RemoteClientService remoteClientService;
    @Resource
    public RedisTemplate redisTemplate;


    /**
     * 商城订单列表
     * @param mallOrderListDTO
     * @return
     */
    @Override
    public List<MallOrderListVO> mallOrderList(MallOrderListDTO mallOrderListDTO) {
        return mallOrderMapper.mallOrderList(mallOrderListDTO);
    }



    @Override
    @Transactional
    public List<MallOrderListVO> mallOrderListComplement(List<MallOrderListVO> list) {
        if (CollUtil.isEmpty(list)) {
            return list;
        }

        for (MallOrderListVO mallOrderListVO : list) {

            // 订单状态为待收货的更新物流信息
            if (mallOrderListVO.getStatus().equals(2)) {
                LogisticsInfoDTO logisticsInfoDTO = getLogisticsInfoDTO(mallOrderListVO.getId(), mallOrderListVO.getLogisticsSn(), mallOrderListVO.getMobile());
                LogisticsInfoVO logisticsInfoVO = BeanUtil.toBean(logisticsInfoDTO.getResult(), LogisticsInfoVO.class);
                // 返回的快递单号可能会出现拼接手机尾号的情况，重新赋值一下
                logisticsInfoVO.setNumber(mallOrderListVO.getLogisticsSn());
                redisTemplate.opsForValue().set(MINAPP_ORDER_LOGISTICS_INFO_KEY + mallOrderListVO.getId(), logisticsInfoVO,6 , TimeUnit.HOURS);

                // 当物流状态为签收时，校验签收时间是否超过7天，超过则订单状态为已完成
                if (!StringUtil.isEmpty(logisticsInfoDTO.getResult().getDeliverystatus()) && logisticsInfoDTO.getResult().getDeliverystatus().equals("3")) {
                    // 签收时间
                    String time = logisticsInfoDTO.getResult().getList().get(0).getTime();
                    boolean exceedSevenDay = com.yfp.common.core.utils.DateUtils.isExceedSevenDay(time);
                    if (exceedSevenDay) {
                        mallOrderListVO.setStatus(MallOrderStatusEnum.COMPLETE.getCode());
                    }
                }
                if (!StringUtil.isEmpty(logisticsInfoDTO.getResult().getDeliverystatus())) {
                    mallOrderListVO.setLogisticsStatus(Integer.valueOf(logisticsInfoDTO.getResult().getDeliverystatus()));
                    mallOrderMapper.updateStatusAndLogisticsStatus(mallOrderListVO);
                }
            }
        }
        return list;
    }


    private LogisticsInfoDTO getLogisticsInfoDTO(Long mallOrderId, String logisticsSn, String mobile) {
        HttpResponse execute = HttpUtil.createGet("https://wuliu.market.alicloudapi.com/kdi")
                .header(Header.AUTHORIZATION, "APPCODE " + "da81a8042ee741f181145252c509e5c6")
                .form("no", logisticsSn + ":" + PhoneUtil.subAfter(mobile))
                .execute();

        if (!execute.isOk()) {
            int httpCode = execute.getStatus();
            Map<String, List<String>> headers = execute.headers();
            String error = headers.get("X-Ca-Error-Message").get(0);
            if (httpCode == 400 && "Invalid AppCode `not exists`".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "AppCode错误");
            } else if (httpCode == 400 && "Invalid Url".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "请求的 Method、Path 或者环境错误");
            } else if (httpCode == 400 && "Invalid Param Location".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "参数错误");
            } else if (httpCode == 403 && "Unauthorized".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "服务未被授权（或URL和Path不正确）");
            } else if (httpCode == 403 && "Quota Exhausted".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "套餐包次数用完");
            } else if (httpCode == 403 && "Api Market Subscription quota exhausted".equals(error)) {
                throw new RuntimeException("物流信息查询失败：" + "套餐包次数用完，请续购套餐");
            } else {
                throw new RuntimeException("物流信息查询失败：" + "参数名错误 或 其他错误");
            }
        }

        LogisticsInfoDTO logisticsInfoDTO = JSONUtil.toBean(execute.body(), LogisticsInfoDTO.class);
        log.info("物流信息查询成功,orderId:{},status:{},msg:{}", mallOrderId, logisticsInfoDTO.getStatus(), logisticsInfoDTO.getMsg());
        return logisticsInfoDTO;
    }


    /**
     * 商城订单退款
     * @param ids
     * @return
     */
    @Override
    public R<Void> mallOrderRefund(List<Long> ids) {

        for (Long id : ids) {
            // 校验订单状态
            MallOrder mallOrder = mallOrderMapper.selectById(id);
            if (!mallOrder.getStatus().equals(2) && !mallOrder.getStatus().equals(3) && !mallOrder.getStatus().equals(7)) {
                return R.fail("订单:"+ mallOrder.getOrderSn() +"不能退款！");
            }
            Response<Boolean> booleanResponse = remoteClientService.mallOrderRefund(id);
            log.info("退款结果{}", booleanResponse);
            if (!booleanResponse.getCode().equals(ResponseEnum.OPERATOR_SUCCESS.getCode())) {
                log.error("订单:{},退款失败{}", mallOrder.getOrderSn(), booleanResponse);
                return R.fail("订单:"+ mallOrder.getOrderSn() + "退款失败，" +booleanResponse.getMsg());
            }
        }
        return R.ok();
    }


    /**
     * 根据商城订单id获取数据
     * @param id
     * @return
     */
    @Override
    public MallOrderListVO getByMallOrderId(Long id) {
        return mallOrderMapper.getByMallOrderId(id);
    }



    /**
     * 录入快递单号
     * @param enteringLogisticsSnDTO
     */
    @Override
    @Transactional
    public void enteringLogisticsSn(EnteringLogisticsSnDTO enteringLogisticsSnDTO) {
        MallOrder mallOrder = mallOrderMapper.selectById(enteringLogisticsSnDTO.getId());
        if (!mallOrder.getStatus().equals(7)) {
            throw new ServiceException("录入失败，订单状态为代发货的订单才能录入快递单号！");
        }

        // 0正常识别   -1无法识别
        Integer code = recognitionLogisticsSn(enteringLogisticsSnDTO.getLogisticsSn());
        if (code != 0) {
            throw new ServiceException("无法识别该快递单号！");
        }

        HttpResponse execute = HttpUtil.createGet("https://wuliu.market.alicloudapi.com/kdi")
                .header(Header.AUTHORIZATION, "APPCODE " + "da81a8042ee741f181145252c509e5c6")
                .form("no", enteringLogisticsSnDTO.getLogisticsSn() + ":" + PhoneUtil.subAfter(mallOrder.getMobile()))
                .execute();

        if (!execute.isOk()) {
            throw new ServiceException("快递单号不正确，未查到物流信息！");
        }

        JsonObject jsonObject = JsonParser.parseString(execute.body()).getAsJsonObject();
        // 获取status的值
        String status = jsonObject.get("status").getAsString();
        if (status.equals("201")) {
            throw new ServiceException(jsonObject.get("msg").getAsString());
        }

        enteringLogisticsSnDTO.setStatus(2);
        if (status.equals("0")) {
            LogisticsInfoDTO logisticsInfoDTO = JSONUtil.toBean(execute.body(), LogisticsInfoDTO.class);
            Integer logisticsStatus = Integer.valueOf(logisticsInfoDTO.getResult().getDeliverystatus());
            enteringLogisticsSnDTO.setLogisticsStatus(logisticsStatus);
            // 当物流状态为签收时，校验签收时间是否超过7天，超过则订单状态为已完成
            if (logisticsStatus.equals(3)) {
                // 签收时间
                String time = logisticsInfoDTO.getResult().getList().get(0).getTime();
                System.out.println();
                boolean exceedSevenDay = DateUtils.isExceedSevenDay(time);
                if (exceedSevenDay) {
                    enteringLogisticsSnDTO.setStatus(3);
                }
            }
        }
        mallOrderMapper.enteringLogisticsSn(enteringLogisticsSnDTO);
    }

    /**
     * 识别快递单号
     */
    public Integer recognitionLogisticsSn(String logisticsSn){

        String host = "https://wuliu.market.alicloudapi.com";// 【1】请求地址 支持http 和 https 及 WEBSOCKET
        String path = "/exCompany";// 【2】后缀
        String appcode = "da81a8042ee741f181145252c509e5c6"; // 【3】开通服务后 买家中心-查看AppCode
        String no = logisticsSn; // 快递单号
        String urlSend = host + path + "?no=" + no; // 【5】拼接请求链接
        try {
            URL url = new URL(urlSend);
            HttpURLConnection httpURLCon = (HttpURLConnection) url.openConnection();
            httpURLCon.setRequestProperty("Authorization", "APPCODE " + appcode);

            StringBuffer sb = new StringBuffer();
            BufferedReader br = new BufferedReader(new InputStreamReader(httpURLCon.getInputStream()));

            int httpCode = httpURLCon.getResponseCode();
            if (httpCode != 200) {
                Map<String, List<String>> map = httpURLCon.getHeaderFields();
                String error = map.get("X-Ca-Error-Message").get(0);
                if (httpCode == 400 && "Invalid AppCode `not exists`".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "AppCode错误");
                } else if (httpCode == 400 && "Invalid Url".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "请求的 Method、Path 或者环境错误");
                } else if (httpCode == 400 && "Invalid Param Location".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "参数错误");
                } else if (httpCode == 403 && "Unauthorized".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "服务未被授权（或URL和Path不正确）");
                } else if (httpCode == 403 && "Quota Exhausted".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "套餐包次数用完");
                } else if (httpCode == 403 && "Api Market Subscription quota exhausted".equals(error)) {
                    throw new RuntimeException("校验物流单号失败：" + "套餐包次数用完，请续购套餐");
                } else {
                    throw new RuntimeException("校验物流单号失败：" + "参数名错误 或 其他错误");
                }
            }
            String line = null;
            while ((line = br.readLine()) != null) {
                line = new String(line.getBytes(), "utf-8");
                sb.append(line);
            }
            br.close();
            String s = sb.toString();
            JsonElement jsonElement = JsonParser.parseString(s);
            JsonObject jsonObject = jsonElement.getAsJsonObject();
            // 0正常识别   -1无法识别
            Integer status = Integer.valueOf(jsonObject.get("status").getAsString());
            return status;
        } catch (Exception e) {
            throw new ServiceException("校验物流单号失败");
        }
    }


}




